#!/usr/bin/perl
#----------------------------------------------------------------------
#
# Generate guc_tables.c from guc_parameters.dat.
#
# Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# src/backend/utils/misc/gen_guc_tables.pl
#
#----------------------------------------------------------------------

use strict;
use warnings FATAL => 'all';

use FindBin;
use lib "$FindBin::RealBin/../../catalog";
use Catalog;

die "Usage: $0 INPUT_FILE OUTPUT_FILE\n" unless @ARGV == 2;
my ($input_fname, $output_fname) = @ARGV;

my $parse = Catalog::ParseData($input_fname);

open my $ofh, '>', $output_fname or die;

print_boilerplate($ofh, $output_fname, 'GUC tables');
foreach my $type (qw(bool int real string enum))
{
	print_one_table($ofh, $type);
}

close $ofh;


# Adds double quotes and escapes as necessary for C strings.
sub dquote
{
	my ($s) = @_;

	return q{"} . $s =~ s/"/\\"/gr . q{"};
}

# Print GUC table for one type.
sub print_one_table
{
	my ($ofh, $type) = @_;
	my $Type = ucfirst $type;

	print $ofh "\n\n";
	print $ofh "struct config_${type} ConfigureNames${Type}[] =\n";
	print $ofh "{\n";

	foreach my $entry (@{$parse})
	{
		next if $entry->{type} ne $type;

		print $ofh "#ifdef $entry->{ifdef}\n" if $entry->{ifdef};
		print $ofh "\t{\n";
		printf $ofh "\t\t{%s, %s, %s,\n",
		  dquote($entry->{name}),
		  $entry->{context},
		  $entry->{group};
		printf $ofh "\t\t\tgettext_noop(%s),\n", dquote($entry->{short_desc});
		if ($entry->{long_desc})
		{
			printf $ofh "\t\t\tgettext_noop(%s)", dquote($entry->{long_desc});
		}
		else
		{
			print $ofh "\t\t\tNULL";
		}
		if ($entry->{flags})
		{
			print $ofh ",\n\t\t\t$entry->{flags}\n";
		}
		else
		{
			print $ofh "\n";
		}
		print $ofh "\t\t},\n";
		print $ofh "\t\t&$entry->{variable},\n";
		print $ofh "\t\t$entry->{boot_val},";
		print $ofh " $entry->{min},"
		  if $entry->{type} eq 'int' || $entry->{type} eq 'real';
		print $ofh " $entry->{max},"
		  if $entry->{type} eq 'int' || $entry->{type} eq 'real';
		print $ofh " $entry->{options},"
		  if $entry->{type} eq 'enum';
		print $ofh "\n";
		printf $ofh "\t\t%s, %s, %s\n",
		  ($entry->{check_hook} || 'NULL'),
		  ($entry->{assign_hook} || 'NULL'),
		  ($entry->{show_hook} || 'NULL');
		print $ofh "\t},\n";
		print $ofh "#endif\n" if $entry->{ifdef};
		print $ofh "\n";
	}

	print $ofh "\t/* End-of-list marker */\n";
	print $ofh "\t{{0}}\n";
	print $ofh "};\n";

	return;
}

sub print_boilerplate
{
	my ($fh, $fname, $descr) = @_;
	printf $fh <<EOM, $fname, $descr;
/*-------------------------------------------------------------------------
 *
 * %s
 *    %s
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * NOTES
 *  ******************************
 *  *** DO NOT EDIT THIS FILE! ***
 *  ******************************
 *
 *  It has been GENERATED by src/backend/utils/misc/gen_guc_tables.pl
 *
 *-------------------------------------------------------------------------
 */
EOM

	return;
}
